﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;

namespace Space.Library
{
    /// <summary>
    /// Immutable.
    /// </summary>
    public class Vector2D
    {
        private const float PiDegrees = (float)(180 / Math.PI);
        public static readonly Vector2D DefaultOrientation = new Vector2D(0, 1);

        public float X { get; private set; }
        public float Y { get; private set; }

        public Vector2D(float x, float y)
        {
            X = x;
            Y = y;
        }

        public Vector2D(Point point)
        {
            X = point.X;
            Y = point.Y;
        }

        public static Vector2D operator -(Vector2D a, Vector2D b)
        {
            return new Vector2D(a.X - b.X, a.Y - b.Y);
        }

        public static Vector2D operator +(Vector2D a, Vector2D b)
        {
            return new Vector2D(a.X + b.X, a.Y + b.Y);
        }

        public static Vector2D operator +(Vector2D a, float b)
        {
            return new Vector2D(a.X + b, a.Y + b);
        }

        public static Vector2D operator -(Vector2D a, float b)
        {
            return new Vector2D(a.X - b, a.Y - b);
        }


        public static Vector2D operator *(Vector2D a, float b)
        {
            return new Vector2D(a.X * b, a.Y * b);
        }


        public static float operator * (Vector2D a, Vector2D b)
        {
            return a.X * b.X + a.Y * b.Y;
        }

        public float Length()
        {
            return (float)Math.Sqrt(X * X + Y * Y);
        }

        /// <summary>
        /// Calculates the angle from default orientation (0,1) to target based on vector from us to target.
        /// </summary>
        public float FindAngleToTarget(Vector2D target)
        {
            var vectorToTarget = target - this;

            var angleRadians = (float)Math.Acos(vectorToTarget * DefaultOrientation  / (vectorToTarget.Length() * DefaultOrientation.Length()));

            // Angle is always smallest angle to y-axis (default orientation) so we swap on -x.
            if (vectorToTarget.X >= 0)
                return PiDegrees * angleRadians;

            return 360 - PiDegrees * angleRadians;
        }

        public override string ToString()
        {
            return string.Format("X = {0}, Y = {1}", X, Y);
        }

        public Vector2D ToUnitVector()
        {
            var length = Length();
            return new Vector2D(X / length, Y / length);
        }
    }
}
